package com.moonciki.artadmin.core.exception;

import com.moonciki.artadmin.core.enums.ResponseEnum;
import com.moonciki.artadmin.core.exception.CustomException;
import com.moonciki.artadmin.core.model.WebResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {

    private void printRequestURI(){
        HttpServletRequest request = ((ServletRequestAttributes)(RequestContextHolder.currentRequestAttributes())).getRequest();

        String requestURI = request.getRequestURI();

        log.warn("requestURI=>{}", requestURI);

    }

    /**
     * 404的异常
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public WebResult notFoundError(Exception e) {
        log.error("notFoundError! {}", e);

        CustomException ce = CustomException.createException(ResponseEnum.not_found.info());

        WebResult resp = WebResult.failResponse(ce);
        return resp;
    }

    private String getShortMsg(String errorMsg){

        if(StringUtils.isNotBlank(errorMsg) && errorMsg.length() > 100){
            errorMsg = "字段类型或格式错误";
        }

        return errorMsg;
    }

    private WebResult validateErrorResult(String fieldName, String errorMsg){
        errorMsg = this.getShortMsg(errorMsg);

        String errorDetail = "[" + fieldName + "]" + errorMsg;

        WebResult resp = WebResult.failResponse(ResponseEnum.request_error.info(errorDetail));

        return resp;
    }

    private WebResult validateErrorResult(String errorMsg){
        errorMsg = this.getShortMsg(errorMsg);

        WebResult resp = WebResult.failResponse(ResponseEnum.request_error.info(errorMsg));

        return resp;
    }

    /**
     * 参数校验异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public WebResult handleBindException(MethodArgumentNotValidException e) {
        FieldError fieldError = e.getBindingResult().getFieldError();

        String fieldName = fieldError.getField();
        String errorMsg = fieldError.getDefaultMessage();
        this.printRequestURI();
        log.warn("Parameter Valid Error! ", e);

        WebResult resp = this.validateErrorResult(fieldName, errorMsg);
        return resp;
    }

    /**
     * 参数校验异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public WebResult handleBindException(BindException e) {
        //校验 除了 requestbody 注解方式的参数校验 对应的 bindingresult 为 BeanPropertyBindingResult

        FieldError fieldError = e.getBindingResult().getFieldError();

        String fieldName = fieldError.getField();
        String errorMsg = fieldError.getDefaultMessage();
        this.printRequestURI();
        log.warn("Parameter Error! ", e);

        WebResult resp = this.validateErrorResult(fieldName, errorMsg);
        return resp;
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public WebResult handleBindException(HttpMessageNotReadableException e) {

        String errorMsg = e.getMessage();
        this.printRequestURI();
        log.warn("Parameter Error! ", e);

        WebResult resp = this.validateErrorResult(errorMsg);
        return resp;
    }

    /**
     * 统一处理所有拦截
     */
    @ExceptionHandler(value = NumberFormatException.class)
    public WebResult handleNumberFormatException(NumberFormatException e) {
        String errorMsg = e.getMessage();
        this.printRequestURI();
        log.warn("Parameter Error!", e);

        WebResult resp = this.validateErrorResult(errorMsg);
        return resp;
    }

    /**
     * 统一处理所有拦截
     */
    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public WebResult handleTypeException(MethodArgumentTypeMismatchException e) {
        String errorMsg = e.getMessage();
        this.printRequestURI();
        log.warn("Parameter Error!", e);

        WebResult resp = this.validateErrorResult(errorMsg);
        return resp;
    }

    /**
     * 统一处理所有拦截
     */
    @ExceptionHandler(value = Exception.class)
    public WebResult handleException(Exception e) {
        this.printRequestURI();
        log.warn("Parameter Error!", e);

        WebResult resp = WebResult.failResponse(e);
        return resp;
    }

}